package com.haoxin.ai_course.modules.course.biz;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.haoxin.ai_course.common.utils.ClientSignUtils;
import com.haoxin.ai_course.common.utils.HttpJsonResult;
import com.haoxin.ai_course.common.utils.HttpUtil;
import com.haoxin.ai_course.common.utils.R;
import com.haoxin.ai_course.config.WxMaConfiguration;
import com.haoxin.ai_course.modules.apkversion.entity.LoginInfo;
import com.haoxin.ai_course.modules.course.entity.PO.DecipherPO;
import com.haoxin.ai_course.modules.course.entity.PO.SysUserPO;
import com.haoxin.ai_course.modules.course.entity.VO.PayStatusVO;
import com.haoxin.ai_course.modules.course.entity.VO.SysUserVO;
import com.haoxin.ai_course.modules.sys.entity.SysUser;
import com.haoxin.ai_course.modules.sys.service.SysUserService;
import com.haoxin.ai_course.modules.sys.service.SysUserTokenService;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import lombok.extern.slf4j.Slf4j;
import ma.glasnost.orika.MapperFacade;

/**
 * 答题结果表
 * 
 * @author xingxiangguo
 * @email bugcn@qq.com
 * @date 2022-06-06 09:44:49
 */
@Slf4j
@Component
public class SysUserBusiness {
	@Autowired
	private MapperFacade mapperFacade;
	@Autowired
	private SysUserService sysUserService;
	@Autowired
	SysUserTokenService sysUserTokenService;
	@Autowired
	WxMaConfiguration wxMaConfiguration;
	@Value("${wechat.miniapp.appid}")
	private String appid;
	@Value("${wechat.miniapp.secret}")
	private String secret;
	final static String accessKeyId = "aiCoursecefca34c0c049056";
	final static String accessSecret = "aiCourse6a395223211ffa";

	public HttpJsonResult<SysUserVO> login(String code) {
//		appid：wxcefca34c0c049056              secret ：gh_c5ed2c9b3681
		String url = "https://api.weixin.qq.com/sns/jscode2session?appid=wxcefca34c0c049056&secret=6a395223211ffa82990e20900f6ee398&js_code="
				+ code + "&grant_type=authorization_code";
		HttpJsonResult<SysUserVO> result = new HttpJsonResult<SysUserVO>();
		String resultStr = HttpUtil.doGet(url, "");
//			String resultStr = "o0hzj5EodEvLWv_OXUXXmQf1BEqg";
		log.info("result:" + resultStr);
		JSONObject jsonResult = JSONObject.parseObject(resultStr);
//			JSONObject jsonResult = new JSONObject();
//			jsonResult.put("openid", "o0hzj5EodEvLWv_OXUXXmQf1BEqg");

		if (jsonResult != null && jsonResult.getString("openid") != null) {
			LoginInfo loginInfo = JSONObject.toJavaObject(jsonResult, LoginInfo.class);
			QueryWrapper<SysUser> qw = new QueryWrapper<SysUser>();
			qw.lambda().eq(SysUser::getOpenid, loginInfo.getOpenid());
			SysUser user = sysUserService.getOne(qw);
			boolean isFirstLogin = false;
			if (user != null) {
				user.setOpenid(loginInfo.getOpenid());
				user.setSessionKey(loginInfo.getSession_key());
				sysUserService.updateById(user);
			} else {
				user = new SysUser();
				user.setStatus(1);
				isFirstLogin = true;
				user.setOpenid(loginInfo.getOpenid());
				user.setUsername(loginInfo.getOpenid());
				user.setPassword(loginInfo.getOpenid());
				user.setSessionKey(loginInfo.getSession_key());
				user.setPayStatus(0);
				sysUserService.save(user);
			}
			R r = sysUserTokenService.createToken(user.getUserId());
			SysUserVO userVO = mapperFacade.map(user, SysUserVO.class);
//			https://cdn-ai-class.wjbrain.com/ai_assets/video/new1.mp4
			userVO.setIsFisrtLogin(isFirstLogin);
			userVO.setToken((String) r.get("token"));
			result.setData(userVO);
		} else {
			result.setMsg("请求失败，接口返回消息：" + resultStr);
			return result;
		}
		return result;
	}

	public HttpJsonResult<Boolean> update(SysUserPO userPO, Long userId) {
		HttpJsonResult<Boolean> result = new HttpJsonResult<Boolean>();
		if (userPO == null || userId == null) {
			result.setMsg("修改用户失败，无效的入参！");
		}
		SysUser user = mapperFacade.map(userPO, SysUser.class);
		user.setUserId(userId);
		user.setUsername(userPO.getMobile());
		user.setMobile(userPO.getMobile());
		result.setData(sysUserService.updateById(user));
		return result;
	}

	public HttpJsonResult<SysUserVO> deciphering(SysUser user, DecipherPO decipherPO) {
		HttpJsonResult<SysUserVO> result = new HttpJsonResult<SysUserVO>();
		final WxMaService wxService = wxMaConfiguration.wxMaService();
		log.info("解密手机号，参数："+JSONObject.toJSONString(decipherPO));
		WxMaPhoneNumberInfo phoneNoInfo = wxService.getUserService().getPhoneNoInfo(decipherPO.getSessionkey(), decipherPO.getEncrypdata(),decipherPO.getIvdata());
		log.info("返回结果："+JSONObject.toJSONString(phoneNoInfo));
//		String str = WxMaCryptUtils.decrypt(decipherPO.getSessionkey(), decipherPO.getEncrypdata(),
//				decipherPO.getIvdata());
//		System.out.println("解密结果---------------:::" + str);
//		JSONObject res = JSONObject.parseObject(str);
//		WxMaPhoneNumberInfo phoneNoInfo = JSONObject.toJavaObject(res, WxMaPhoneNumberInfo.class);
		user.setMobile(phoneNoInfo.getPhoneNumber());
		user.setUsername(phoneNoInfo.getPhoneNumber());
		log.info("解密后修改用户，用户信息：{}",JSONObject.toJSON(user));
		
		sysUserService.updateById(user);
		SysUserVO sysUserVO = mapperFacade.map(user, SysUserVO.class);
		sysUserVO.setIsFisrtLogin(false);
		result.setData(sysUserVO);
		return result;
	}

	/**
	 * 创建用户，提供给互医平台调用
	 * 
	 * @param user
	 * @param userId
	 * @return
	 * @throws Exception
	 */
	public HttpJsonResult<Boolean> createUser(Map<String, String> params, String sign) throws Exception {
		HttpJsonResult<Boolean> result = new HttpJsonResult<Boolean>();
//		 {
//			    "id"：111，//用户编号，唯一
//			    "legalName": "1", // 姓名
//			    "phone": "1", // 联系方式
//			    "gender": 1, // 1:男 2:女
//			    "dob": "1998-11-19" // 出生日期，格式yyyy-MM-dd
//			}
//			验签
		String timeStampStr  =  params.get("timeStamp");
		log.info("验证签名,参数时间:" + timeStampStr);
		log.info("验证签名,系统时间:" + System.currentTimeMillis());
		if(StringUtils.isAllBlank(timeStampStr)) {
			result.setMsg("未找到时间戳信息");
			return result;
		}
		Long timeStamp = Long.parseLong(timeStampStr);
		if(System.currentTimeMillis()-timeStamp>60*1000) {
			result.setMsg("签名过期");
			return result;
		}
		
		if (!checkSign(params, sign)) {
			result.setMsg("签名无效");
			return result;
		}
//			入库处理
		String mobile = (String) params.get("phone");
		String name = (String) params.get("legalName");
		log.info("互医调起支付接口：mobile：{},name:{}",mobile,name);
		QueryWrapper<SysUser> qw = new QueryWrapper<SysUser>();
		qw.lambda().eq(SysUser::getUsername, mobile).or().eq(SysUser::getMobile, mobile);
		SysUser user = sysUserService.getOne(qw);
		if (user == null) {
			log.info("互医调起支付接口：用户不存在，创建用户",mobile,name);
			user = new SysUser();
			user.setUsername(mobile);
			user.setFullName(name);
			user.setPassword(mobile);
			user.setStatus(1);
			user.setPayStatus(1);
			user.setMobile(mobile);
			sysUserService.save(user);
		}else {
			user.setUsername(mobile);
			user.setFullName(name);
			user.setMobile(mobile);
			user.setPassword(mobile);
			user.setPayStatus(1);
			log.info("互医调起支付接口：用户存在，修改用户",mobile,name);
			sysUserService.updateById(user);
		}
		result.setMsg("用户信息同步成功");
		result.setData(true);
		log.info("互医调起支付接口结束：用户信息:{}",user);
		return result;
	}

	public HttpJsonResult<JSONObject> checkPayStatus(String tel, String pSign, String timeStampStr, boolean needSign) throws Exception {
		log.info("检查支付状态，tel:{},needSign:{},",tel,needSign);
		HttpJsonResult<JSONObject> result = new HttpJsonResult<JSONObject>();
		JSONObject data = new JSONObject();
		if (needSign ) {
			if(StringUtils.isAllBlank(timeStampStr)) {
				result.setMsg("未找到时间戳信息");
				return result;
			}
			Long timeStamp = Long.parseLong(timeStampStr);
			if(System.currentTimeMillis() - timeStamp > 60*1000) {
				result.setMsg("签名过期");
				return result;
			}
			SortedMap<String, String> params = new TreeMap<String, String>();
			params.put("tel", tel);
			params.put("timeStamp", timeStampStr);
			String sign = ClientSignUtils.sign(params, accessSecret);
			log.info("检查支付状态，传入的签名：{}，生成的签名:{}",pSign ,sign);
			if(sign.equals(pSign)) {
				result.setMsg("签名无效");
				data.put("paymentContent", "签名无效");
				result.setData(data);
			}
			return result;
		}
//		验证是否支付
		QueryWrapper<SysUser> qw = new QueryWrapper<SysUser>();
		qw.lambda().eq(SysUser::getUsername, tel);
		SysUser user = sysUserService.getOne(qw);
		if (user != null && user.getPayStatus() ==1) {
			R r = sysUserTokenService.createToken(user.getUserId());
			data.put("paymentContent", "用户已支付");
			data.put("token", r.get("token"));
			data.put("expire", r.get("expire"));
			result.setData(data);
			result.setCode(0);
		} else {
			data.put("paymentContent", "用户未支付");
			result.setData(data);
			result.setCode(0);
		}
		log.info("检查支付状态结束，结果：tel{},result:{}",tel,data);
		return result;
	}
	public HttpJsonResult<PayStatusVO> checkPaymentWithSign(String tel, String pSign, String timeStampStr) throws Exception {
		HttpJsonResult<PayStatusVO> result = new HttpJsonResult<PayStatusVO>();
			if(StringUtils.isAllBlank(timeStampStr)) {
				result.setMsg("未找到时间戳信息");
				return result;
			}
			Long timeStamp = Long.parseLong(timeStampStr);
			if(System.currentTimeMillis()-timeStamp>60*1000) {
				log.info("检查支付状态，参数时间戳：" + timeStampStr);
				log.info("检查支付状态，系统时间戳：" + System.currentTimeMillis());
				result.setMsg("签名过期");
				return result;
			}
			SortedMap<String, String> params = new TreeMap<String, String>();
			params.put("tel", tel);
			params.put("timeStamp", timeStampStr);
			String sign = ClientSignUtils.sign(params, accessSecret);
			log.info("检查支付状态，传入的签名：{}，生成的签名:{}",pSign ,sign);
			if(!sign.equals(pSign)) {
				result.setMsg("签名无效");
				PayStatusVO payStatusVO = new PayStatusVO();
				result.setData(payStatusVO);
				return result;
			}
//		验证是否支付
		QueryWrapper<SysUser> qw = new QueryWrapper<SysUser>();
		qw.lambda().eq(SysUser::getUsername, tel);
		SysUser user = sysUserService.getOne(qw);
		PayStatusVO payStatusVO= new PayStatusVO();
		if (user != null && user.getPayStatus() ==1) {
			payStatusVO.setPayStatus(1);
			payStatusVO.setPayMsg("用户已支付");
		} else {
			payStatusVO.setPayStatus(0);
			payStatusVO.setPayMsg("用户未支付");
		}
		result.setData(payStatusVO);
		result.setCode(0);
		
		return result;
	}

	public static boolean checkSign(Map<String, String> params, String pSign) throws Exception {
		SortedMap<String, String> map = new TreeMap<>();
		Set<String> keys = params.keySet();
		for (String key : keys) {
			if (key.equals("sign")) {
				continue;
			}
			map.put(key, params.get(key));
		}
		log.error("验证签名，参数：" + map);
		String sign = ClientSignUtils.sign(map, accessSecret);
		log.error("验证签名，生成的签名：" + sign);
		return sign.equals(pSign);
	}

	public static String HMACSHA256(String data, String key) throws Exception {

		Mac sha256_HMAC = Mac.getInstance("HmacSHA256");

		SecretKeySpec secret_key = new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256");

		sha256_HMAC.init(secret_key);

		byte[] array = sha256_HMAC.doFinal(data.getBytes("UTF-8"));

		StringBuilder sb = new StringBuilder();

		for (byte item : array) {

			sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));

		}

		return sb.toString().toUpperCase();

	}

	public HttpJsonResult<SysUserVO> getPhone(String code, SysUser user) {
		HttpJsonResult<SysUserVO> result = new HttpJsonResult<SysUserVO>();
		String token_url = String.format(
				"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s", appid,
				secret);
		JSONObject token = JSON.parseObject(HttpUtil.get(token_url));
		log.info("获取token返回结果---------------:::" + token+" appid:"+appid+"  secret:"+secret);
		// 使用前端code获取手机号码 参数为json格式
		String url = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token="
				+ token.getString("access_token");
		JSONObject paramMap = new JSONObject();
		paramMap.put("code", code);
		String resultStr = HttpUtil.doPost(url, paramMap.toJSONString());
//		{"errcode":0,"errmsg":"ok","phone_info":{"phoneNumber":"18335122243","purePhoneNumber":"18335122243","countryCode":"86","watermark":{"timestamp":1657858846,"appid":"wxcefca34c0c049056"}}}
		log.info("返回结果---------------:::" + resultStr);
		JSONObject res = JSONObject.parseObject(resultStr);
		if(res.getIntValue("errcode") !=0) {
			result.setMsg("换取手机号失败，微信返回结果："+resultStr);
			
			return result;
		}
		WxMaPhoneNumberInfo phoneNoInfo = JSONObject.toJavaObject(res.getJSONObject("phone_info"), WxMaPhoneNumberInfo.class);
		user.setMobile(phoneNoInfo.getPhoneNumber());
		user.setUsername(phoneNoInfo.getPhoneNumber());
		SysUser dbUser = sysUserService.getById(user.getUserId());
		QueryWrapper<SysUser> qw = new QueryWrapper<SysUser>();
		qw.lambda().eq(SysUser::getMobile, phoneNoInfo.getPhoneNumber());
		SysUser ofLineUser = sysUserService.getOne(qw);
		if(!phoneNoInfo.getPhoneNumber().equals(dbUser.getMobile())||!phoneNoInfo.getPhoneNumber().equals(dbUser.getUsername())) {
			dbUser.setMobile(phoneNoInfo.getPhoneNumber());
			dbUser.setUsername(phoneNoInfo.getPhoneNumber());
			if(ofLineUser!=null) {
				ofLineUser.setOpenid(dbUser.getOpenid());
				ofLineUser.setSessionKey(dbUser.getSessionKey());
				log.info("修改存在用户的支付状态,用户信息:{}",ofLineUser);
				sysUserService.updateById(ofLineUser);
				sysUserService.removeById(dbUser);
			}else {
				sysUserService.updateById(dbUser);
			}
			
		}
		SysUserVO sysUserVO = mapperFacade.map(dbUser, SysUserVO.class);
		sysUserVO.setIsFisrtLogin(false);
		result.setData(sysUserVO);
		return result;
	}

	public static void main(String[] args) {
        System.out.println(6&11);
	}

}
